#ifndef _PROGRAM_H
#define _PROGRAM_H

#include <string>
#include <vector>
#include "define.h"

// TODO: SysController is a singleton, so this class needn't be singleton?
// Or maybe it's ok, just forbid user to create multiple instances
class ProgramManager {
public:
	static ProgramManager *instance();

	int LoadProgram(const std::string& path);
	int SaveProgram(const std::string& path);
	void InitProgram();

	int InsertItem(int item_index, ushort item_code);
	int RemoveItem(int item_index);

	// return current program file path
	const std::string& programFilePath() const
	{ return file_path_; }

	program_s *program() const;

	// if the item at item_index is not an active item,
	// return NULL
	item_s *item(int item_index) const;

	// return current item count
	int itemCount() const;

	// check if the prog is dirty and not saved
	bool IsChangedAndUnsaved() const;

	int setDeviceType(ushort dev_code);
	ushort deviceType() const;

	// MEASURE OPTIONS

	int setMeasOptMeasMode(ushort meas_mode);
	ushort measOptMeasMode() const;
	int setMeasOptFfs(bool enable);
	bool measOptFfs() const;
	int setMeasOptCntClr(bool enable);
	bool measOptCntClr() const;
	int setMeasOptDataFile(bool enable);
	bool measOptDataFile() const;

	// GLOBAL OPTIONS

	int setOptEndTime(double end_time);
	double optEndTime() const;
	int setOptOffTime(double off_time);
	double optOffTime() const;
	int setOptWarnNgCnt(int warn_ng_cnt);
	int optWarnNgCnt() const;
	int setOptFilterFreq(ushort freq_code);
	ushort optFilterFreq() const;
	int setOptHdrLogic(int hdr_logic);
	int optHdrLogic() const;
	int setOptDlmCoef(double coef);
	double optDlmCoef() const;
	int setOptSelStep(bool enable);
	bool optSelStep() const;

	// ITEM OPERATIONS
	
	int itemIndex(const std::string& item_name, char item_suffix);
	ushort itemCode(int item_index) const;
	char itemSuffix(int item_index) const;
	int setItemChannel(int item_index, int ch);
	int itemChannel(int item_index) const;
	int setItemWaitTime(int item_index, double wait_time);
	double itemWaitTime(int item_index) const;
	int setItemBiasRng(int item_index, ushort rng_code);
	ushort itemBiasRng(int item_index) const;
	int setItemBiasVal(int item_index, double val);
	double itemBiasVal(int item_index);
	int setItemMeasRng(int item_index, ushort rng_code);
	ushort itemMeasRng(int item_index) const;
	int setItemMeasVal(int item_index, bool lower, double val);
	double itemMeasVal(int item_index, bool lower) const;
	int setItemVolLimit(int item_index, double limit);
	double itemVolLimit(int item_index);
	int setItemLimitJudge(int item_index, bool enable);
	bool itemLimitJudge(int item_index) const;
	int setItemFilterOpt(int item_index, ushort fil_code);
	ushort itemFilterOpt(int item_index);

	// DETAIL OPTIONS
	
	std::vector<int> RefItemList(int item_index) const;

	int setEsdRefItem(int itm_idx, int ref_idx, int ref_itm_idx);
	int esdRefItem(int itm_idx, int ref_idx) const;

	int setHueAutoRange(int item_index, bool enable);
	bool hueAutoRange(int item_index) const;
	int setHueOfstCancel(int item_index, bool enable);
	bool hueOfstCancel(int item_index) const;
	int setHuePreAmpRng(int item_index, int pre_amp_idx, ushort rng_code);
	ushort huePreAmpRng(int item_index, int pre_amp_idx) const;
	int setHueAmpScf(int item_index, int amp_idx, ushort scf_code);
	ushort hueAmpScf(int item_index, int amp_idx) const;

private:
	ProgramManager();
	
	// is there an item in the given index
	bool IsValidItem(int item_index) const;

	char GenerateItemSuffix(int item_index, ushort item_code);		
	// Is there more than 2 VF items before this index for ESD
	bool IsEsdEnabled(int item_index) const;
	void InitEsdConfig(int item_index);
	void InitMasterConfig(int item_index);
	
	// when insert/delete, items after the insertion/deletion position
	// should be moved forward/backward 1 step
	void MoveItems(int item_index, bool insert);

	// for debug
	void PrintAllItems() const;

	static const std::string kProgramFileSuffix;
	static ProgramManager *instance_;

	std::string file_path_;	
};


#endif // _PROGRAM_H
